﻿using FinScreen.Analyzers;
using FinScreen.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using FinScreen.Util;
using System.Reactive;
using System.Threading;
using FinScreen.Connectors;
using FinScreen.ViewModel;
using QuantBox.CSharp2CTPZQ;
using TdxConnector;

namespace FinScreen
{
    public partial class MainForm : Form
    {
        private readonly QuantBase _quantBase = new QuantBase();
        private readonly MasterBase _masterBase = new MasterBase();
        private readonly MarketBase _marketbase = new MarketBase();
        private readonly List<Strategy> _strategies = new List<Strategy>();
        private IDisposable _lastDispose;
        private readonly Statistics _statistics =new Statistics();

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e) 
        {
            _strategies.AddRange(Strategy.Discover(StrategyEnum.All));

            var root = tvStrategies.Nodes.Add("ALL");
            _strategies.ForEach(p =>
            {
                var node = new TreeNode(p.Attribute.Name) {Tag = p};
                root.Nodes.Add(node);
            });

            tvStrategies.ExpandAll();

            instrumentsGridView.Clear<DisplayInstrument>();

            _masterBase.Subscribe((instrument) => { Task.Run(() => { _quantBase.Load(new Instrument[] { instrument }); }); });
            _quantBase.Subscribe(p =>
                {
                    _statistics.OnQuant(p);
                    lblUpDownStocks.Invoke(new Action(() =>
                        {
                            lblUpDownStocks.Text = _statistics.UpDownStockRatio.ToString("N2");
                        }));
                });

            Task.Run(() =>
                {
                    _masterBase.Load();
                    _marketbase.Load();
                });
        }
        private void tvStrategies_AfterSelect(object sender, TreeViewEventArgs e)
        {
            try
            {
                if (e.Node == null || e.Node.Tag == null)
                {
                    instrumentsGridView.BindingList<DisplayInstrument>().Clear();

                    foreach (var p in _masterBase)
                        instrumentsGridView.BindingList<DisplayInstrument>().Add(new DisplayInstrument(p));

                    runStrategyStripButton.Enabled = false;
                    stopStrategytoolStripButton.Enabled = false;
                }
                else
                {
                    var strategy = e.Node.Tag as Strategy;
                    instrumentsGridView.BindingList<DisplayInstrument>().Clear();
                    if (strategy != null)
                    {
                        var instruments = strategy.Instrument(new StrategyContext(_masterBase, _quantBase, _marketbase));
                        if (instruments != null)
                        {
                            instruments.ToList().ForEach(p => instrumentsGridView.BindingList<DisplayInstrument>().Add(new DisplayInstrument(p)));

                            if (_lastDispose != null) _lastDispose.Dispose();

                            _lastDispose = _marketbase.Subscribe((p) => Invoke(new Action<CThostFtdcDepthMarketDataField>((p1) =>
                                {
                                    var ins = instrumentsGridView.BindingList<DisplayInstrument>().SingleOrDefault((x) =>
                                        {
                                            string id = x.Code.Split('.')[0];
                                            return id == p1.InstrumentID;
                                        });
                                    if (ins == null) return;
                                    ins.MarketPrice = Math.Round(p1.LastPrice,2);
                                    ins.PctChange = Math.Round((p1.LastPrice - p1.PreClosePrice) / p1.PreClosePrice * 100, 2);
                                    ins.NetChange = Math.Round(p1.LastPrice- p1.PreClosePrice,2);
                                    ins.High = Math.Round(p1.HighestPrice,2);
                                    ins.Low = Math.Round(p1.LowestPrice,2);

                                    instrumentsGridView_DataBindingComplete(instrumentsGridView, 
                                        new DataGridViewBindingCompleteEventArgs(ListChangedType.ItemChanged));

                                    instrumentsGridView.Refresh();
                                }), p));
                        }
                    }
                    if (strategy != null)
                    {
                        runStrategyStripButton.Enabled = !strategy.Running;
                        stopStrategytoolStripButton.Enabled = strategy.Running;
                    }
                }
            }
            catch (Exception)
            { }
        }

        private void buyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                using (var client = new TdxClient("BasicHttpBinding_ITdxService"))
                {
                    client.Open();
                }
            }
            catch (Exception)
            {
            }
        }

        private void sellToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                using (var client = new TdxClient("BasicHttpBinding_ITdxService"))
                {
                    client.Open();
                }
            }
            catch
            {
            }
        }

        private void timeTimer_Tick(object sender, EventArgs e)
        {
            this.Text = "天狼星   现在时间-"+DateTime.Now.ToString();
        }

        private void runStrategyStripButton_Click(object sender, EventArgs e)
        {
            if (tvStrategies.SelectedNode == null) return;
            var strategy = tvStrategies.SelectedNode.Tag as Strategy;
            if (strategy == null) return;

            var instruments =
                instrumentsGridView.BindingList<DisplayInstrument>()
                .Select(p => _masterBase.SingleOrDefault(p1 => p1.Code == p.Code));

            strategy.Run(instruments, new StrategyContext(_masterBase, _quantBase, _marketbase));

            tvStrategies.SelectedNode.Text = strategy.Attribute.Name + "...";
            tvStrategies.SelectedNode.ForeColor = Color.Red;

            runStrategyStripButton.Enabled = !strategy.Running;
            stopStrategytoolStripButton.Enabled = strategy.Running;
        }

        private void stopStrategytoolStripButton_Click(object sender, EventArgs e)
        {
            if (tvStrategies.SelectedNode == null) return;
            var strategy = tvStrategies.SelectedNode.Tag as Strategy;
            if (strategy == null) return;

            strategy.Stop(new StrategyContext(_masterBase, _quantBase, _marketbase));

            tvStrategies.SelectedNode.Text = strategy.Attribute.Name + "...";
            tvStrategies.SelectedNode.ForeColor = Color.Black;

            runStrategyStripButton.Enabled = !strategy.Running;
            stopStrategytoolStripButton.Enabled = strategy.Running;
        }

        private void instrumentsGridView_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            for (int i = 0; i < instrumentsGridView.Rows.Count; ++i)
            {
                var cell = instrumentsGridView.Rows[i].Cells[4];
                double v = 0f;
                if (double.TryParse(cell.Value.ToString(), out v))
                    cell.Style.ForeColor = v > 0 ? Color.Red : (v == 0 ? Color.Black : Color.Green);
                else
                    cell.Style.ForeColor = Color.Black;

                instrumentsGridView.Rows[i].Cells[3].Style.ForeColor = cell.Style.ForeColor;
                instrumentsGridView.Rows[i].Cells[5].Style.ForeColor = cell.Style.ForeColor;
            }
        }

        private void refreshPnlToolStripButton_Click(object sender, EventArgs e)
        {
            Task.Run(() =>
                {
                    try
                    {
                        using (var client = new TdxClient("BasicHttpBinding_ITdxService"))
                        {
                            client.Open();
                            var positions = client.GetPositions();

                            foreach (var position in positions)
                            {
                                Invoke(new Action<Position>((p) =>
                                    {
                                        pnlGridView.BindingList<DisplayPosition>()
                                            .Add(new DisplayPosition(p));
                                    }), position);
                            }
                        }
                    }
                    catch (Exception)
                    {
                    }
                });
        }
    }

    
}
